package dfs;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

/**
 * MaximumDepthOfBinaryTree
 *
 * @author <a href="zhaoyingling12@163.com">Zhao Simon</a>
 * @description: 二叉树的最大深度 https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/
 * @date 2021/6/18
 **/
public class MaximumDepthOfBinaryTree {

    /**
     * 使用深度优先搜索，从root节点开始向下递归
     */
    class Solution1 {

        int max = Integer.MIN_VALUE;

        public int maxDepth(TreeNode root) {
            Set<TreeNode> visited = new HashSet<>();
            if (root == null) return 0;
            dfs(root, visited, 1);
            return max == Integer.MIN_VALUE ? 0 : max;
        }

        public void dfs(TreeNode node, Set<TreeNode> visited, int step) {
            if (visited.contains(node)) {
                return;
            } else {
                visited.add(node);
            }
            if (node.right == null && node.left == null) {
                max = Math.max(max, step);
            }
            if (node.left != null) {
                dfs(node.left, visited, step + 1);
            }
            if (node.right != null) {
                dfs(node.right, visited, step + 1);
            }
        }
    }


    /**
     * 使用深度优先搜索，从叶子节点开始递归
     */
    class Solution2 {

        public int maxDepth(TreeNode root) {
            if (root == null) {
                return 0;
            }
            int leftHeight = maxDepth(root.left);
            int rightHeight = maxDepth(root.right);
            return Math.max(leftHeight, rightHeight) + 1;
        }
    }

    /**
     * 使用广度优先搜索
     */
    class Solution3 {

        public int maxDepth(TreeNode root) {
            if (root == null) {
                return 0;
            }
            Queue<TreeNode> queue = new LinkedList<TreeNode>();
            queue.offer(root);
            int ans = 0;
            while (!queue.isEmpty()) {
                int size = queue.size();
                while (size > 0) {
                    TreeNode node = queue.poll();
                    if (node.left != null) {
                        queue.offer(node.left);
                    }
                    if (node.right != null) {
                        queue.offer(node.right);
                    }
                    size--;
                }
                // 遍历完1层加1
                ans++;
            }
            return ans;
        }

    }
}
